/*
 * @(#)ModQueryTable.java 1.00 7 Sep 2007
 *
 * Copyright (c) 2005-2007 Soluciones Info Móviles S.A.C.
 * Av. Javier Prado Oeste 203 - Piso 13, Lima 27, Perú.
 * Todos los derechos reservados.
 */
package sim.query;

import sim.framework.*;
import sim.framework.gui.*;
import sim.forms.*;
import sim.store.*;
import sim.utils.Utils;

/**
 * Consulta una tabla con criterios de búsqueda.
 *
 * @author      Enrique Madrid <e.madrid@lpcsite.com>
 * @author      Omar Quintana <o.quintana@lpcsite.com>
 * @since   1.0
 */
public abstract class ModQueryTable extends ModQuery {
    
    protected static final int MOD_SQL = -1;

    //public static final int STATE_LOAD = STATE_USE;
        
    private ModSql     m_Criteria = null;
    private StoreTxt   m_Table    = null;
    private DataTxt    m_Record   = null;
    private StoreTxtId m_RecordId = new StoreTxtId();
    private boolean    m_CriteriaRequested = false;
    
    /**
     * Crea una nueva instancia de ModQueryTable.
     */    
    public ModQueryTable(int id, Simlet s, int nFields, boolean multiopt) {
        super(id, s, multiopt);
        m_Record = new DataTxt(StoreTxt.FIELD_TOKEN, nFields, s.getAppEncoding());
    }
    
    public ModQueryTable(int id, Simlet s, int nFields) {
        this(id, s, nFields, false);
    }

    public void work(final Msg msg) {
        switch (msg.getWParam()) {
            case STATE_INIT:
                workInit(msg);
                break;
            case STATE_NEXT:
                workNext(msg);
                break;
            case STATE_BACK:
                workBack(msg);
                break;
//             case STATE_LOAD:
//                 workLoad(msg);
//                 break;
            default:
                super.work(msg);
        }
    }
    
    /**
     * Método llamado cuando se llama a #work() con estado
     * <code>STATE_INIT</code>.
     */
    private void workInit(final Msg msg) {
        // Si no se ha solicitado el criterio de busqueda ...
        if (!m_CriteriaRequested) {
            // solicitad uno ...
            m_CriteriaRequested = true;
            m_Criteria = (ModSql)createModule(MOD_SQL);
            if (m_Criteria != null) {
                // Ejecutar el módulo que captura el criterio ...
                execQueue(this, this);
                exec(m_Criteria);
                return;
            }
        }
        m_Table = queryTableOpen();
        if (m_Table == null) {
            execBack();
        }
        super.work(msg);
    }
    
    /**
     * Método llamado cuando se llama a #work() con estado
     * <code>STATE_NEXT</code>.
     */
    private void workNext(final Msg msg) {
        // El módulo que captura el criterio a regresado,
        // el la clase padre, requiere entrar por STATE_INIT
        todo(STATE_INIT);
    }
    
    /**
     * Método llamado cuando se llama a #work() con estado
     * <code>STATE_BACK</code>.
     */
    private void workBack(final Msg msg) {
	queryTableClose();
        execBack();
    }

//     private void workLoad(final Msg msg) {
// 	if (!isWorking()) {
// 	}
//     }
    
    /**
     * FUNCIONES AUXILIARES.
     *
     */
    
    protected int getField() {
        if (m_Criteria != null) {
            return m_Criteria.getField();
        }
        return 0;
    }
    
    protected byte[] getValue() {
        if (m_Criteria != null) {
            return m_Criteria.getValue();
        }
        return null;
    }
    
    protected int getValueLength() {
        if (m_Criteria != null) {
            if (m_Criteria.getValue() != null) {
                return m_Criteria.getValue().length;
            }
        }
        return 0;
    }
    
    /**
     * IMPLEMENTANDO Y REDEFINIENDO CALLBACKS DE LA CLASE SUPER.
     *
     */
    
    protected int querySearch() {
        //#ifdef DEBUG_MODQUERYTABLE
        //# 	System.out.println("ModQueryTable::querySearch() ENTERED");
        //#endif
        if (m_Table.select(m_RecordId, getField(), getValue(), 0, getValueLength(), false)) {
            if (m_Table.load(m_RecordId, m_Record)) {
                return queryTableHit(m_Record);
            }
        }
        //#ifdef DEBUG_MODQUERYTABLE
        //# 	System.out.println("ModQueryTable::querySearch() EXITING");
        //#endif
        return ModQuery.QUERY_STOP;
    }
    
    /**
     * INTERCEPTANDO CALLBACKS DE LA CLASE SUPER.
     *
     */
    
    protected final void queryWhatIs(int itemId) {
        //#ifdef DEBUG_MODQUERYTABLE
        //# System.out.println("ModQueryTable::queryWhatIs() ENTERED");
        //#endif
        
        //#ifdef DEBUG_MODQUERYTABLE
        //# System.out.println("\t itemId = " + itemId);
        //#endif
        
        queryTableInfo(Gui.KEY_STAR, itemId);
        //#ifdef DEBUG_MODQUERYTABLE
        //# System.out.println("ModQueryTable::queryWhatIs() EXITING");
        //#endif
        
    }
    
    protected final void queryTellMe(int itemId) {
        queryTableInfo(Gui.KEY_POUND, itemId);
    }
    
    protected final void queryShowMe(int itemId) {
        queryTableInfo(Gui.KEY_NONE, itemId);
    }
    
    private void queryTableInfo(int key, int itemId) {
        //#ifdef DEBUG_MODQUERYTABLE
        //# System.out.println("ModQueryTable::queryTableInfo() ENTERED");
        //#endif
        
        if (m_Table.load(itemId, m_Record)) {
            switch (key) {
                case Gui.KEY_STAR:
                    queryTableWhatIs(m_Record);
                    break;
                case Gui.KEY_POUND:
                    queryTableTellMe(m_Record);
                    break;
                case Gui.KEY_NONE:
                    queryTableShowMe(m_Record);
                    break;
            }
        }
        //#ifdef DEBUG_MODQUERYTABLE
        //# System.out.println("ModQueryTable::queryTableInfo() EXITING");
        //#endif
        
    }
    
    protected final void queryGoToNext() {
	// Damos la oportunidad de cargar un registro de la tabla y
	// notificamos al la derivada que el usuario decide continuar.
        queryTableGoToNext();
	// Cerramos la tabla.
        queryTableClose();
    }
    
    protected final void queryGoToBack() {
	// Cerramos la tabla.
        queryTableClose();
	// Notificamos al la derivada que el usuario decide cancelar.
        queryTableGoToBack();
    }
    
    private void queryTableClose() {
        if (m_Table != null) {
            m_Table.close();
            m_Table = null;
        }
    }
    
    /**
     * DECLARANDO CALLBACKS PARA CLASE DERIVADA.
     *
     */
    
    protected abstract StoreTxt queryTableOpen();
    
    protected abstract int queryTableHit(final DataTxt record);
    
    protected void queryTableWhatIs(final DataTxt record) {
        appendText(null);
    }
    
    protected void queryTableTellMe(final DataTxt record) {
        appendText(null);
    }
    
    protected void queryTableShowMe(final DataTxt record) {
        appendText(null);
    }
    
    protected void queryTableGoToNext() {
        execNext();
    }
    
    protected void queryTableGoToBack() {
        execBack();
    }
    
    /** 
     * Devuelve el primer registro seleccionado.
     * 
     * 
     * @return Devuelve una referencia a un objeto del tipo DataTxt.
     */
    protected final DataTxt firstRecord() {
        int id;
	if (m_Table != null) {
	    id = firstId();
	    if (id != GuiCtrl.INVALID_ITEM_ID) {
		if (m_Table.load(id, m_Record)) {
		    return m_Record;
		}
	    }
	}
        return null;
    }
    
    /** 
     * Devuelve el siguiente registro seleccionado.
     * 
     * 
     * @return Devuelve una referencia a un objeto del tipo DataTxt.
     */
    protected final DataTxt nextRecord() {
        int id;
	if (m_Table != null) {
	    id = nextId();
	    if (id != GuiCtrl.INVALID_ITEM_ID) {
		m_Record = new DataTxt(StoreTxt.FIELD_TOKEN, 
				       m_Record.size(), 
				       m_Simlet.getAppEncoding());
		if (m_Table.load(id, m_Record)) {
		    return m_Record;
		}
	    }
	}
        return null;
    }
}
